using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Calais.RDFSProcess
{
    public class CalaisEnumBuilder
    {
        private readonly XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
        private readonly XNamespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";
        private const string calaisEntity = "http://s.opencalais.com/1/type/em/e/";
        private const string calaisRelationship = "http://s.opencalais.com/1/type/em/r/";
        private const string calaisDisambiguatedEntity = "http://s.opencalais.com/1/type/er/";

        private Dictionary<string, string> _entities = new Dictionary<string, string>();
        private Dictionary<string, string> _relationships = new Dictionary<string, string>();
        private Dictionary<string, string> _systemEntities = new Dictionary<string, string>();
        private Dictionary<string, string> _disabiguatedEntities = new Dictionary<string, string>();

        public void Process()
        {
            Process(string.Empty);
        }

        public void Process(string name)
        {
            XNamespace calais;

            var doc = XDocument.Load("RDFS.xml");
            this.Ensure(i => doc != null, new Exception("Unable to process response!"));

            calais = doc.Root.Descendants(rdf + "Description").First().Attribute(rdf + "about").Value;

            IEnumerable<XElement> classes;

            if (string.IsNullOrEmpty(name))
            {
                classes = from item in doc.Root.Descendants(rdfs + "Class")
                          select item;
            }
            else
            {
                classes = from item in doc.Root.Descendants(rdfs + "Class")
                          where item.Attribute(rdf + "about").Value.EndsWith(name)
                          select item;
            }

            if (classes.Count() == 0)
            {
                return;
            }

            foreach (var item in classes)
            {
                string about = item.Attribute(rdf + "about").Value;
                string label = item.Element(rdfs + "label").Value;
                string comment = item.Element(rdfs + "comment").Value;

                //Console.WriteLine("{0} - {1} - {2}", about, label, comment);

                if(about.Contains(calaisEntity))
                {
                    _entities.Add(label,comment);
                }
                else if(about.Contains(calaisRelationship))
                {
                    _relationships.Add(label,comment);
                }
                else if(about.Contains(calaisDisambiguatedEntity))
                {
                    label = label.Replace("-dis", "Dis");
                    _disabiguatedEntities.Add(label,comment);
                }
                else
                {
                    _systemEntities.Add(label,comment);    
                }
            }
        }

        public string GenerateEnum(CalaisEnumType type)
        {
            switch (type)
            {
                case(CalaisEnumType.DisambiguatedEntities):
                    {
                        return GenerateEnum(_disabiguatedEntities, "CalaisRdfDisambiguatedEntityType");  
                    }

                case(CalaisEnumType.Relationships):
                    {
                        return GenerateEnum(_relationships, "CalaisRdfRelationshipType");
                    }

                case(CalaisEnumType.SystemEntities):
                    {
                        return GenerateEnum(_systemEntities, "CalaisRdfSystemEntityType");
                    }

                default:
                    {
                        return GenerateEnum(_entities, "CalaisRdfEntityType");
                    }
            }
        }

        public string GenerateEnum(Dictionary<string, string> collection, string name)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("\tpublic enum {0}\n", name);
            sb.AppendLine("\t{");

            foreach (var entity in collection)
            {
                //sb.AppendFormat("\t\t[EnumString(\"{0}\")]\n", entity.Value);
                sb.AppendFormat("\t\t{0}", entity.Key);

                if(entity.Key != collection.Last().Key)
                {
                    sb.AppendLine(",");
                }
                else
                {
                    sb.AppendLine();
                }
            }

            sb.AppendLine("\t}");
            return sb.ToString();
        }

        public string GenerateAllEnums()
        {
            var sb = new StringBuilder();

            foreach (var e in Enum.GetNames(typeof(CalaisEnumType)))
            {
                sb.Append(GenerateEnum((CalaisEnumType)Enum.Parse(typeof(CalaisEnumType),e)));
                sb.AppendLine();
            }

            return sb.ToString();
        }
    }

    public enum CalaisEnumType
    {
        Entities,
        Relationships,
        SystemEntities,
        DisambiguatedEntities
    }
}